package informationretrieval;

import static informationretrieval.Constants.NAME_ID;
import informationretrieval.readers.Parameter;
import informationretrieval.readers.ParameterFileReader;

import java.io.FileWriter;
import java.util.HashMap;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;

import org.apache.lucene.document.Document;
import org.apache.lucene.benchmark.quality.QualityStats;

public class Lucene {

	// Class variables
	private static final String TAG = Lucene.class.getSimpleName();
	private static String mOutputFile;
	private static String mParametersFileName;
	private static FileWriter mFileWriter = null;
	private static ResultSet mTruthRank;
	private static DocsDatabase mDocsDatabase;
	private static ParameterFileReader mParams;
	private static HashMap<Integer, String> mQueries;
	private static SortedSet<Integer> mQueryIds;

	public static void main(String[] args) {
		try {
			// Method variables
			boolean inComparingMode = false;
			ResultSet actualTop5 = new ResultSet();
			ResultSet actualTop10 = new ResultSet();

			// Get the parameter file name from the argument line in case it exists
			// Or from a default config otherwise
			mParametersFileName = (args[0] == null) ? Parameter.INPUT_FILE
					.getName() : args[0];
			mParams = new ParameterFileReader(mParametersFileName);
			
			// Instantiate class variables
			mQueries = mParams.getParameter(Parameter.QUERY_LIST);
			mOutputFile = mParams.getParameter(Parameter.OUTPUT_FILE);
			mDocsDatabase = mParams.getParameter(Parameter.DOCS_DATABASE);

			// read the ground truth file
			if (mParams.containsParameter(Parameter.TRUTH_RANK)) {
				inComparingMode = true;
				mTruthRank = mParams.getParameter(Parameter.TRUTH_RANK);
			}
			
			// prepare the output file
			if (mParams.containsParameter(Parameter.OUTPUT_FILE)) {
				inComparingMode = false;
				mFileWriter = new FileWriter(mOutputFile);
			}

			// Sort the queries in the hashmap by their id
			mQueryIds = new TreeSet<Integer>(mQueries.keySet());

			// Iterate on the query set and get the results for every query
			for (int queryId : mQueryIds) {
				// Fetch a single query and serach for the relevant result in the corpus
				String searchQuery = mQueries.get(queryId);
				SearchResult result = mDocsDatabase.search(searchQuery);
				
				// Get the result set we got as a list plus 
				// the absolute true rank and the false result set
				// to calculate the ndcg value
				List<Integer> queryResultSet = result.getQueryResultSet();
				List<Integer> trueResultSet = mTruthRank.getTrueRankList(queryId);
				List<Integer> falseResultSet = Functions.getFalseResultSet(mDocsDatabase.getDocCorpusSize(), trueResultSet);
				double ndcgValue = NDCG.calculateNDCGValue(queryResultSet, trueResultSet, falseResultSet);
				double mapValue = Precision.calculateMAP(queryResultSet, trueResultSet, falseResultSet);
				for (int rank = 0; rank < result.getScoreDoc().length; rank++) {
					int docId = result.getScoreDoc()[rank].doc;
					float score = result.getScoreDoc()[rank].score;
					Document doc = result.getDoc(docId);
					String stringDocId = String.format("doc%s",
							doc.getField(NAME_ID).stringValue());
					String stringQueryId = String.format("q%s", queryId);

					Log.trace(stringQueryId + "," + stringDocId + "," + rank
							+ "," + score);
				}

				if (inComparingMode) {
					Functions
							.updateResultsCount(result, queryId, actualTop5, 5);
					Functions.updateResultsCount(result, queryId, actualTop10,
							10);
				} else {
					Log.writeResultsToFile(mFileWriter, result, queryId, ndcgValue, mapValue);
				}
			}

			if (inComparingMode) {
				Functions.calculateAndSaveComparingResults(mTruthRank,
						actualTop10);
			}

		} catch (Exception exception) {
			Log.error(TAG, exception, true);
		} finally {
			if (mFileWriter != null) {
				try {
					mFileWriter.close();
				} catch (Exception exception) {
					Log.error(TAG, exception, true);
				}
			}
		}

	}

}